/*
 * Copyright 2003-2005 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */

using System;

using TypeElement = argot.TypeElement;
using TypeException = argot.TypeException;
using TypeInputStream = argot.TypeInputStream;
using TypeOutputStream = argot.TypeOutputStream;
using TypeReader = argot.TypeReader;
using TypeWriter = argot.TypeWriter;

namespace argot.common
{
	
	public class BigEndianUnsignedLong 
	:TypeReader, TypeWriter
	{
		
		public const System.String TYPENAME = "u64";
		
		public unsafe virtual System.Object Read(TypeInputStream inStream, TypeElement element)
		{
			byte[] array = new byte[8];
			
			if ( inStream.Stream.Read( array,0,8 ) < 8 )
				throw new System.IO.EndOfStreamException();

			if ( BitConverter.IsLittleEndian )
			{
				byte b = array[0]; array[0] = array[7]; array[7] = b;
				b = array[1]; array[1] = array[6]; array[6] = b;
				b = array[2]; array[2] = array[5]; array[5] = b;
				b = array[3]; array[3] = array[4]; array[4] = b;
			}

			fixed( byte* parray = array )
			{
				return *((System.UInt64 *)parray);
			}
		}
		
		public virtual void Write(TypeOutputStream outStream, System.Object o, TypeElement element)
		{
			int a, b, c, d, e, f, g, h;
			
			if (!(o is System.Int64))
				throw new TypeException("U32B: requires Long");
			
			long s = (long) ((System.Int64) o);
			
			if (s < MIN || s > MAX)
				throw new TypeException("U16B: value out of range: " + s);
			
			a = (int) ((s >> 56) & 0xff);
			b = (int) ((s >> 48) & 0xff);
			c = (int) ((s >> 40) & 0xff);
			d = (int) ((s >> 32) & 0xff);
			e = (int) ((s >> 24) & 0xff);
			f = (int) ((s >> 16) & 0xff);
			g = (int) ((s >> 8) & 0xff);
			h = (int) (s & 0xff);
			
			outStream.Stream.WriteByte((System.Byte) a);
			outStream.Stream.WriteByte((System.Byte) b);
			outStream.Stream.WriteByte((System.Byte) c);
			outStream.Stream.WriteByte((System.Byte) d);
			outStream.Stream.WriteByte((System.Byte) e);
			outStream.Stream.WriteByte((System.Byte) f);
			outStream.Stream.WriteByte((System.Byte) g);
			outStream.Stream.WriteByte((System.Byte) h);
		}
		
		public const long MIN = 0;
		public const long MAX = 9223372036854775807L; //2^63-1;
	}
}